/*
 * Copyright(C) 2022. Huawei Technologies Co.,Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MXBASE_HEADPOSEESTIMATIONV2
#define MXBASE_HEADPOSEESTIMATIONV2
#include "MxBase/MxBase.h"
#include "opencv2/opencv.hpp"
#include "MxBase/postprocess/include/ObjectPostProcessors/Yolov3PostProcess.h"
#include "MxBase/postprocess/include/KeypointPostProcessors/OpenPosePostProcess.h"
#include <memory>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include "mxpiOpenposeProto.pb.h"
#include "chrono"
#include "time.h"
#include "BlockingQueue.h"

namespace Openpose
{
  struct PartPair
  {
    float score;
    int partIdx1;
    int partIdx2;
    int idx1;
    int idx2;
    std::vector<float> coord1;
    std::vector<float> coord2;
    float score1;
    float score2;
  };

  struct V2Param
  {
    uint32_t deviceId;
    std::string modelPath;
    V2Param() {}
    V2Param(const uint32_t &deviceId, const std::string &modelPath)
        : deviceId(deviceId), modelPath(modelPath) {}
  };
  class OpV2Cppv2
  {
  public:
    uint32_t deviceId = 0;
    std::string modelPath;
    std::shared_ptr<MxBase::ImageProcessor> imageProcessorDptr;
    std::shared_ptr<MxBase::Model> OpV2Dptr;
    std::vector<MxBase::Tensor> OpV2Outputs;
    explicit OpV2Cppv2(const V2Param &v2Param);
    bool MergeSkeletonToPerson(std::vector<std::vector<PartPair>> &personList, PartPair currentPair);
    float PersonScore(const std::vector<PartPair> &person);
    bool GreaterSort(PartPair p1, PartPair p2);
    std::vector<float> OneSkeletonScore(std::vector<cv::Point> &endpoints,
                                        const cv::Mat &pafX, const cv::Mat &pafY);
    APP_ERROR ConntectionNms(std::vector<PartPair> &src, std::vector<PartPair> &dst);
    APP_ERROR GetImage(const std::string &imgPath, std::shared_ptr<uint8_t> &dataPtr, uint32_t &dataSize);
    APP_ERROR ReadImage(const std::string &imgPath, MxBase::Image &decodedImage);
    APP_ERROR OpInfer(MxBase::Image &resizeImage, std::vector<MxBase::Tensor> &OpV2Outputs);
    APP_ERROR GeneratePersonList(std::vector<MxBase::Tensor> &OpV2Outputs,
                                 std::vector<std::vector<PartPair>> &personList,
                                 mxpiopenposeproto::MxpiPersonList &dstMxpiPersonList, bool isEval);
    APP_ERROR ResizeHeatmaps(std::vector<cv::Mat> &keypointHeatmap,
                             std::vector<cv::Mat> &pafHeatmap,
                             std::vector<int> &visionInfos);
    APP_ERROR ExtractKeypoints(std::vector<cv::Mat> &keypointHeatmap,
                               std::vector<std::vector<cv::Point>> &coor,
                               std::vector<std::vector<float>> &coorScore);
    APP_ERROR GroupKeypoints(const std::vector<cv::Mat> &pafHeatmap,
                             const std::vector<std::vector<cv::Point>> &coor,
                             const std::vector<std::vector<float>> &coorScore,
                             std::vector<std::vector<PartPair>> &personList);
    APP_ERROR GenerateMxpiOutput(const std::vector<std::vector<PartPair>> &personList,
                                 mxpiopenposeproto::MxpiPersonList &dstMxpiPersonList, bool isEval);
    APP_ERROR ScoreSkeletons(const int partIndex,
                             const std::vector<std::vector<cv::Point>> &coor,
                             const std::vector<std::vector<float>> &coorScore,
                             const std::vector<cv::Mat> &pafHeatmap,
                             std::vector<PartPair> &connections);

  private:
    std::string parentName_;
    std::string imageDecoderName_;
    std::uint32_t inputHeight_;
    std::uint32_t inputWidth_;
    std::ostringstream ErrorInfo_;
  };
}
#endif
